首先我們要創建一個計時器的函式,先找出當下開始的時間與結束的時間,用setInterval()
方法執行倒數秒數,每1000毫秒(1秒)會執行一次顯示一次當下秒數,藉由結束時間扣除當下的時間,如果secondsLeft
變成0,那麽我們需要清除計時器,並且結束。
let countdown;
function timer(seconds) {
//Date.now會以毫秒計算現在的時間
const now = Date.now();
//傳入的秒數也需要換算成毫秒,並加上想執行的時長
const then = now + seconds * 1000;
//每指定的時間到就執行function
countdown = setInterval(() => {
//剩餘的秒數需要預計的時間扣掉每一秒顯示的時間
//但是會發現這樣扣除時間時會有小數點的誤差,所以用Math.round四捨五入進位回原本的數值。
const secondsLeft = Math.round((then - Date.now()) / 1000);
if (secondsLeft < 0) {
clearInterval(countdown);
return;
}
console.log(secondsLeft);
}, 1000);
}
但假如我們執行timer(10)
,第一次回傳的秒數會是9
,但希望可以從傳入的參數開始倒數計時,所以我們需要一個函式,不僅在每次使用setInterval()
倒數時,都能從指定的時間開始顯示倒數,也能夠渲染在畫面上。
function timer(seconds) {
const now = Date.now();
const then = now + seconds * 1000;
//顯示一開始的時間
displayTimeLeft(seconds);
countdown = setInterval(() => {
const secondsLeft = Math.round((then - Date.now()) / 1000);
if (secondsLeft < 0) {
clearInterval(countdown);
return;
}
//顯示開始計時的時間
displayTimeLeft(secondsLeft);
}, 1000);
}
function displayTimeLeft(seconds) {
//Math.floor會往負數捨去後面小數點到最接近的整數
const minute = Math.floor(seconds / 60);
//取秒數除以分鐘的餘數
const remainderSeconds = seconds % 60;
//${remainderSeconds < 10 ? "0" : ""}這段是決定秒數小於10時要出現0為開頭
const display = `${minute}:${remainderSeconds < 10 ? "0" : ""}${remainderSeconds}`;
//讓網頁的名稱可以顯示當下倒數計時的秒數
document.title = display;
//插入時間
timerDisplay.textContent = display;
}
在網頁的中間有斗大的計時器,下面會接一行顯示結束的時間,所以我們需要做顯示計時器的做法,能把結束時間一起渲染出來。
function timer(seconds) {
const now = Date.now();
const then = now + seconds * 1000;
displayTimeLeft(seconds);
//將預計結束的時間傳進去
displayEndTime(then);
countdown = setInterval(() => {
const secondsLeft = Math.round((then - Date.now()) / 1000);
if (secondsLeft < 0) {
clearInterval(countdown);
return;
}
displayTimeLeft(secondsLeft);
}, 1000);
}
function displayEndTime(timestamp){
//轉換時間格式
//產生這個物件之後,可以得到像是月份的數值
const end = new Date(timestamp);
//取得指定時間單位的數值
const hour = end.getHours();
const minute = end.getMinutes();
//因為習慣24小時制,所以就不讓hour超過12之後減去12
endTime.textContent = `Be Back At${hour}:${minute< 10 ? "0" : ""}${minute}`
}
最上方分別已經有設定好的時間跟樣式,只要在相對的按鈕中執行相對時間就可以了,但是如果我們分別按太多時間,會導致事件變得不太正常,所以要在計時器的一開始就先清除。
function timer(seconds) {
//每一次執行都要清除上一回執行的計時器
clearInterval(countdown);
const now = Date.now();
const then = now + seconds * 1000;
displayTimeLeft(seconds);
//將預計結束的時間傳進去
displayEndTime(then);
countdown = setInterval(() => {
const secondsLeft = Math.round((then - Date.now()) / 1000);
if (secondsLeft < 0) {
clearInterval(countdown);
return;
}
displayTimeLeft(secondsLeft);
}, 1000);
}
function startTimer(event){
const seconds = parseInt(event.target.dataset.time)
timer(seconds);
}
buttons.forEach(button => button.addEventListener('click', startTimer));
右上角有一欄可以自行指定倒數時間的輸入框,首先要在submit
停止預設事件,防止按出之後直接更新,再來就執行時間,不過我在中間有擋掉自行輸入0
或者不是數字的內容。
比較特別的是form
只要有name
屬性,就能透過這個屬性得到已經存在的節點。
function getTime(event){
event.preventDefault();
const minutes = Number(this.minutes.value)
if (Number.isNaN(minutes)||minutes===0){
alert('please input number')
return;
}
timer(minutes*60);
this.reset();
}
document.customForm.addEventListener('submit',getTime);
MDN
Math.round()
clearInterval() global function
W3School
JavaScript Timing Events
JavaScript Math.floor()